Repository navigation
Make patch 0005 near upstream speed with in-line F16 checks (#174) - #182
Merged
Merged
Conversation
) Patch 0005 widened every F16 product of ggml_vec_dot_f16 to F32, which halved F16-weight decode on linux_armv8.2_2 (conversion path) and cost prefill on linux_armv8.6_1. It now keeps upstream's F16 multiply-adds and reduction for at most 64 products per lane, adds each block into F32, and recomputes a nonfinite result with the previous F32 kernel. Finite results for n < 2080 are bit-identical to upstream. The F16 test models the patched dot exactly on FP16 vector arithmetic modules and adds block, rounding, lane-overflow, NaN-overflow, tail, unpadded and NaN/inf input cases.
…174) Rows of up to 2048 elements run upstream's F16 code in-line and check the reduced F16 vector before conversion; longer rows and the F32 recompute run out of line. Adds one-block overflow cases and measured performance.
The Linux variant smoke allows four F16 roundings for its 64-element dot, and NaN/inf input cases run only on the patched path: upstream's other F16 dot paths assert a finite sum in debug builds.
leehack
marked this pull request as ready for review
November 7, 2026 23:00
This was referenced Nov 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Makes patch 0005 (
ggml_vec_dot_f16, #174, upstream ggml-org/llama.cpp#31734) about as fast as unpatched upstream while keeping its overflow guarantee. The first 0005 ran every dot in F32 and cost up to 2x in F16 decode onlinux_armv8.2_2.Design
Same approach as 0006 (#179), for non-SVE NEON with FP16 vector arithmetic. x86, SVE and MSVC paths are unchanged.
sum - sum == 0in every lane) runs before conversion to F32. The double scalar tail is upstream's.noinline): each 64-step block is reduced the same way and added into F32 lanes, with anisfinitecheck on the F32 sum before the tail.noinline, FMLAL/FMLAL2 with FP16 FML, otherwise conversion plus F32 FMA). Acoldattribute made an all-overflow matrix 4.3x slower, so the recompute is onlynoinlineplus__builtin_expect.Contract
n < 2080(one block plus tail), every finite result is bit-identical to unpatched upstream. Longer rows add their per-block F16 sums in F32. Within a block, F16 rounding is upstream's, so results are not F32-accurate.Tests and mutants
tests/f16_dot_accumulation_test.cppnow models the patched dot exactly: upstream's F16 multiply-adds per lane, its reduction order, 64-step blocks, F32 lanes and the double tail. It needs a bit-exact match wherever the model is finite. New cases:Mutants were run on the Apple FMLAL build and the conversion build (
GGML_CPU_ARM_ARCH=armv8.2-a+fp16+dotprod), with identical results:29 of the 30 mutants are killed. The one survivor is equivalent.
Performance
Qwen2.5-0.5B-Instruct (F16 and Q8_0), CPU, 8 threads, F16 KV. Each value is new 0005 + 0006 relative to unpatched
v0.9.0, as the median over interleaved rounds (5 on M4, 3 on GCE). Ranges cover FA off/on and both decode tests.linux_armv8.2_2linux_armv8.2_2linux_armv8.6_1linux_armv8.6_1, where F16 is 0.98 / 0.99 and Q8_0 FA off is 0.98. On that variant llamafile is compiled out under I8MM, so every F16 matmul goes throughggml_vec_dot_f16and the per-row check is visible. The remaining M4 F16 prefill gap is 0006: 0006 alone measures 0.93 / 0.94.Verification
tools/linux_cpu_variant_smoke.cnow allows the error of four F16 roundings (2^-9 × absolute sum) on its 64-element dot. The first 0005 was F32-accurate, so the old 2e-6 bound broke at magnitude 30 (83328 against 83313). The failure reproduced on M4 and passes there with the new bound.linux_armv8.2_2/linux_armv8.6_1/baseline modules on Neoverse-N1 and Neoverse-V2. GCE built the hot path withcoldon the recompute; that hot path is instruction-identical to this head.tools/llama_cpp_patches.py apply --strict: 0005 alone applies on v0.7.0, v0.8.0 and v0.9.0; the full series applies on v0.8.0 and v0.9.0.tools/validate_linux_arm64_cpu_isa.pypasses on both Linux modules, which are GCC 13.3 builds of this head. Inlinux_armv8.6_1, FMLAL appears only in the recompute (10 instructions) and in 0006.linux_armv8.2_2has no FMLAL.High-risk native kernel change. Independent audit: ACCEPT at
57a8aa43against maineb760895, with no blocking findings.armv8.2_2is 1.47–1.49×.